package com.tcm.pay.common;

import cn.hutool.core.util.XmlUtil;
import com.base.core.utils.JacksonUtils;
import com.base.core.utils.R;
import com.tcm.pay.domain.pojo.BaseRequest;
import com.tcm.pay.enums.BusinessCodeEnum;
import com.tcm.pay.util.Base64Util;
import com.tcm.pay.util.RSAutil;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

public class HttpRequest {

    //一麻袋公钥
    private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCEW2qCO++81e4nz7Y4nQ2ilQmkQAOWJfpa9hli\n" +
            "f/S2Vrln9VmKs5bgZhCMIcUcDAqw5RyRbdgBUbks0HJKZ0EcgPuWaamH1t07Zi0qg6s0uQx4ueS5\n" +
            "6Q745wZWUB/W2oVTpUc1BTihMD5fVtC/YhM2TSXLgC771jsnVQZxBueq+wIDAQAB";

    //交易私钥
    private static final String priKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIRbaoI777zV7ifPtjidDaKVCaRA\n" +
            "A5Yl+lr2GWJ/9LZWuWf1WYqzluBmEIwhxRwMCrDlHJFt2AFRuSzQckpnQRyA+5ZpqYfW3TtmLSqD\n" +
            "qzS5DHi55LnpDvjnBlZQH9bahVOlRzUFOKEwPl9W0L9iEzZNJcuALvvWOydVBnEG56r7AgMBAAEC\n" +
            "gYALkO2CyfgOOWehZP5Yfij13y5DgzCNC26QSlc3i1T4JiX3lrInc8AoheLGTCEsbUT15l+TudSZ\n" +
            "cOnMp76FD/bZhZ4ttm1ansBLvxQTcquyUPwpuv8hzpwmnmNuRPE5DHMrnVD/tgyO6BYdomT0SMDC\n" +
            "lYJPFrxjlqZw7F4uNccE2QJBAL8rPlykRRoKEn/WHfL1RZHZZhSS7ANmZomCQ5MDD+aebt8aiz1s\n" +
            "sLMSnTr/yMz0k2K9Gji+X4gzrJmzLIt4ab0CQQCxPkrhv1jQoYUZqgjSXouTFc6D2FEmQK1uAhlt\n" +
            "WDqyc1cBxw7BwAGgCU59gV2szxlcLTbMLduwPCfdj61DGgcXAkBRpVBvFKGGq4KXIoWL/IEH94eH\n" +
            "hfBSy2tDk2T05rvlzQihNJ7/TupwsKSCTDgggNxpsUX/sh7u9tLimgmOT5EpAkBwmHL3gBgKyWEF\n" +
            "kbfy9C7UrHi51xSOKW5DQUAn73GyZYUzUuI0ASbHJMJhBmqc2h9xKCP0h3lVNpHYtWpLA2DXAkEA\n" +
            "r2wriFKkf3kalerOyhtkCzLRb3qtJnxWH6slSZrXQW4g+kdZWABoLDV5FitXzwO7nF4KD+Ypk/jW\n" +
            "dF6ZDiDhfQ==";

    public static String postRequest(String url, Object data) throws Exception {
        HttpsClient client = new HttpsClient(url);
        BaseRequest request = createBaseData(data);
        client.addParam("requestTime", request.getRequestTime());
        client.addParam("version", request.getVersion());
        client.addParam("merchantNo", request.getMerchantNo());
        client.addParam("requestData", request.getRequestData());
        client.addParam("encryptKey", request.getEncryptKey());
        client.addParam("sign", request.getSign());
        return client.sendHttps(10000);
    }

    public static BaseRequest createBaseData(Object object) throws Exception {
        BaseRequest demoBaseRequest = new BaseRequest();
        demoBaseRequest.setVersion("1.0");
        demoBaseRequest.setMerchantNo("50829");
        demoBaseRequest.setRequestTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));

        String content = JacksonUtils.toJSONString(object);
        //获取AESKey
        String aesKey = AESEncrypt.generateAESKey();
        //AES 加密 content 在使用前进行Base64转码
        String data = AESEncrypt.encryptECB(Base64.encodeBase64String(content.getBytes(StandardCharsets.UTF_8)), aesKey);
        //对 content 进度AES加密后的密文 赋值给requestData
        demoBaseRequest.setRequestData(data);
        //对 aesKey 进行RSA 加密
        String encryptKey = RSAEncrypt.encrypt(RSAObtainKey.loadPublicKeyByStr(publicKey), aesKey.getBytes(StandardCharsets.UTF_8));
        //对 aesKey 进度RSA加密后的密文 赋值给 encryptKey
        demoBaseRequest.setEncryptKey(encryptKey);
        //拼接签名参数，requestData+requestTime+merchantNo
        String signContent = demoBaseRequest.getRequestData() + demoBaseRequest.getRequestTime() + demoBaseRequest.getMerchantNo();
        //签名数据 signContent 在加签前需要进行Base64 转码
        signContent = Base64.encodeBase64String(signContent.getBytes(StandardCharsets.UTF_8));
        //对 signContent 进行 RSA 签名
        String signResult = RSASignature.sign(signContent, priKey);
        demoBaseRequest.setSign(signResult);
        return demoBaseRequest;
    }

    /**
     * 扫码支付签名
     *
     * @param MerNo
     * @param BillNo
     * @param Amount
     * @param OrderTime
     * @param AdviceUrl
     * @return
     */
    public static String makeSignForScanPay(String MerNo, String BillNo, String Amount, String OrderTime, String AdviceUrl) {
        String sign;
        try {
            String plain = "MerNo=" + MerNo + "&" + "BillNo=" + BillNo + "&" + "Amount=" + Amount + "&" +
                    "OrderTime=" + OrderTime + "&" + "AdviceUrl=" + AdviceUrl;
            sign = RSAutil.sign(plain, RSAutil.getPrivateKey(priKey));
        } catch (Exception e) {
            return e.getMessage();
        }
        return sign;
    }

    /**
     * 聚合支付签名
     *
     * @param AdviceUrl
     * @param Amount
     * @param MerchantNo
     * @param MerchantOrderNo
     * @param PayType
     * @param RandomStr
     * @return
     */
    public static String makeSignForAggregatePay(String AdviceUrl, String Amount, String MerchantNo, String MerchantOrderNo, String PayType, String RandomStr) {
        String sign;
        try {
            String plain = "AdviceUrl=" + AdviceUrl + "&" + "Amount=" + Amount + "&" + "MerchantNo=" + MerchantNo + "&" +
                    "MerchantOrderNo=" + MerchantOrderNo + "&" + "PayType=" + PayType+ "&" + "RandomStr=" + RandomStr;
            sign = RSAutil.sign(plain, RSAutil.getPrivateKey(priKey));
        } catch (Exception e) {
            return e.getMessage();
        }
        return sign;
    }

    public static Map<String, Object> postRequestDomain(String url, String requestDomain) {
        Map<String, Object> res = null;
        try {
            HttpsClient client = new HttpsClient(url);
            client.addParam("requestDomain", requestDomain);
            String xml = client.sendHttps(10000);
            res = XmlUtil.xmlToMap(xml);
        } catch (Exception e) {
            R.throwFail(BusinessCodeEnum.BILL_NO_NOT_EXISTS.getCode(),e.getMessage());
        }
        return res;
    }

    /**
     * 商户入驻签名
     *
     * @param merNo
     * @param payType
     * @param randomStr
     * @return
     */
    public static String makeSignForMerchantIn(String merNo, String payType, String randomStr) {
        String sign;
        try {
            String plain = "MerNo=" + merNo + "&" + "PayType=" + payType + "&" + "RandomStr=" + randomStr;
            sign = RSAutil.sign(plain, RSAutil.getPrivateKey(priKey));
        } catch (Exception e) {
            System.out.println("签名出错：" + e.getMessage());
            return "123456";
        }
        return sign;
    }

    /**
     * 商户请求
     *
     * @param url
     * @param data
     * @param request
     */
    public static String sendData(String url, String data, String request) {
        HttpsClient client = new HttpsClient(url);
        //base64后的密文赋值-------请求参数【requestDomain】中
        client.addParam("requestDomain", data);
        String xml = "";
        try {
            String result = client.sendHttps(10000);
            //注意结果 需要保存。
            xml = new String(Base64Util.decode(result));
        } catch (Exception e) {
            e.printStackTrace();

        }
        return xml;
    }

    /**
     * 商户查询签名
     *
     * @param merNo
     * @param payType
     * @param companyNo
     * @param randomStr
     * @return
     */
    public static String makeSignForQueryMerchantIn(String merNo, String payType, String companyNo, String randomStr) {
        String sign;
        try {
            String plain = "MerNo=" + merNo + "&" + "CompanyNo=" + companyNo + "&" + "PayType=" + payType + "&" + "RandomStr=" + randomStr;
            sign = RSAutil.sign(plain, RSAutil.getPrivateKey(priKey));
        } catch (Exception e) {
            System.out.println("签名出错：" + e.getMessage());
            return "123456";
        }
        return sign;
    }

    /**
     * 代付接口签名
     *
     * @return
     */
    public static String makeSignForTransferFixed(String transId, String accountNumber, String cardNo, String amount) {
        String sign;
        try {
            String plain = "transId=" + transId + "&" + "accountNumber=" + accountNumber + "&" + "cardNo=" + cardNo + "&" +
                    "amount=" + amount ;
            sign = RSAutil.sign(plain, RSAutil.getPrivateKey(priKey));
        } catch (Exception e) {
            return e.getMessage();
        }
        return sign;
    }

}
